
/*
*Released on 28th June 2008.
*Any violations can be reported at paritosh@wikiocean.net
*What is treated as violations can be found at www.wikiocean.net/ppl1-voilations*
******************************************************************************
* The contents of this file are subject to POOL Public License 1.0 and later.
* POOL Public License is based on Affero GPL v3 and additional conditions.
* ("License"); You may not use this file except in compliance with the License
* You may obtain a copy of the Affero GPL v3 License at http://www.gnu.org/licenses/agpl.html
* You may obtain a copy of the POOL Public License 1.0 or later at www.wikiocean.net/license/ppl.html
* Software distributed under POOL Public License 1.0 is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
* The Initial Developer of the Original Code is Paritosh Pungaliya (C) 2008. All Rights Reserved.
******************************************************************************
* Objective of the additional terms (license)
* 1) Is to extend the software freedom to freedom to work.
* 2) To ensure that knowledge is free from monopoly of agencies.
* 3) To avoid a situation where big corporate or investor can buy out free software groups and companies and then start milking the communities built around it.
* (this trend can be seen how the freedom is curtailed in companies that get Venture Capital funding.)
******************************************************************************
*/

package  query.query;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.RandomAccessFile;
import java.sql.ResultSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import logger.PoolLogger;

import property.Order;
import file.SearchRecord;
import utility.CapitalChar;
import utility.ConvertToLower;
import utility.Index;
import database.RecordSearch;
import dbmanager.Column;
import dbmanager.DBManager;
import dbmanager.GetIdName;

/**
 * <pre>Query can contain a Query within it. It may be on same table or different one,  but the actual mapping will be done at Join only. As compare to SQL the Query  is mapped with Select Clause in SQL.</pre>
 * @author     mahendra
 */
public class Query  implements Queryinterface 
{	
	/**
	 * @uml.property  name="querybuffer"
	 */
	String [] Querybuffer;
	String Query="SELECT distinct  FROM";
	GetIdName gid;
	String tablename="report_master";
	String object;
	/**
	 * @uml.property  name="buffer"
	 */
	String[] buffer;
	int Querycount=1;
	static int QueryMaxcount=1;
	String QUERY="query";
	Hashtable<Object, Object> QueryMap = new Hashtable<Object, Object>();
	Vector<Object> ConditionMap = new Vector<Object>();
	SearchRecord sr;
	Order order ;
	String packagename ="query.query.";
	/**
	 * @uml.property  name="key"
	 */
	String Key="no$";
	String value = "no$";
	/**
	 * @uml.property  name="queryName"
	 */
	String QueryName;
	String Filename;
	String tid;
	String process;
	/**
	 * @uml.property  name="reportName"
	 */
	String ReportName;
	String KEY="key"; 
	String CONDITION="condition";
	String typeofreport;
	Hashtable<Object, Object> table = new Hashtable<Object, Object>();
	Hashtable<Object, Object> result =new Hashtable<Object, Object>();
	Hashtable<Object, Object> Reportmap =new Hashtable<Object, Object>();
	Queryinterface query;
	String reporton;
	int minCount;
	Vector<Object > queryVector =new Vector<Object>();

	PoolLogger pl;
	
	public Query() {
		// logger
		pl = (PoolLogger) PoolLogger.getLogger(this.getClass().getName());
	}
	

	/**
	 * set Dbmanager object
	 * @param db :  Dbmanager object
	 */
	
	
	public void initPool()
	{
		gid = new GetIdName();
		KEY = gid.getId(KEY);
		CONDITION = gid.getId(CONDITION);
		QUERY =  gid.getId(QUERY);
		order = new Order();
	}
	/**
	 * set Query Object 
	 * @param Object  : String
	 * @uml.property  name="object"
	 */
	public void setObject(String object)
	{
		this.object = object;
	}
	/**
	 * this method set Querybuffer to result of inner query  
	 * @param  Querybuffer
	 * @uml.property  name="querybuffer"
	 */
	public void setQuerybuffer(String Querybuffer[])
	{
		this.buffer = Querybuffer;
	}
	/**
	 * initializeData()  method find object of query,condition,field,key,sortby,tablename and put into querymap
	 */
	@SuppressWarnings("unchecked")
	public void initializeData()
	{
		result.put("tablename", "report_master");
		
		try 
		{
			
			Hashtable<Object, Object> temp = new Hashtable<Object, Object>();
			//String MasterPath = Input.MASTERREPORTSPATH + object + "//" + object + "_mid" + Input.FILRFORMAT;
			//sr = new SearchRecord(MasterPath);
			RecordSearch rs =new RecordSearch();
			temp.put("mid",object);
			temp.put("td", "null");
			rs.setConditionMap(temp);
			String line[] = rs.getArrayFromResultSet();
			QueryMap.clear();
//			setting default table name to report_master
			QueryMap.put(gid.getId("tablename"), "report_master");
			
			try {
				if(!ConditionMap.isEmpty()&& Querycount==1)
				{
					QueryMap.put(gid.getId("condition"), "");
					result.put("condition", "");
				}	
				if(typeofreport.equalsIgnoreCase("systemgenerate") && Querycount==1 || QueryMap.containsKey(KEY))
				{
					QueryMap.put(gid.getId("condition"), "");
					result.put("condition", "");
				}	
				
			} catch (Exception e) {
				
			}
			for(int i=0;i<line.length;i++)
			{
				String splitstr[]  = line[i].split("\t");
				String value = splitstr[Column.pv_index-1];
				if(value.equals("0"))
					value = splitstr[Column.vt_index-1];
				else
					value = gid.getItem(splitstr[Column.pv_index-1]);
				QueryMap.put((splitstr[Column.pid_index-1]) , value);
			}
			this.QueryMap = ConvertToLower.convertHashKey(QueryMap);			
			//String MASTERPATH = Input.MASTERREPORTSPATH + object + "//" + object + "_mid" + Input.FILRFORMAT;
			//sr = new SearchRecord(MASTERPATH);

			table.put("mid", object);
			rs.setConditionMap(temp);
			line = rs.getArrayFromResultSet();
			result.putAll(gethashtabelofResult(line));
		} catch (Exception e1) {
			e1.printStackTrace();
			result.putAll(QueryMap);
		}		
		
			
		
	//	result = gid.ConvertKeytoMasterName(result);
		table = order.getSequences(QUERY);
		table = ConvertToLower.convertHashKey(table);
		result = ConvertToLower.convertHashKey(result); 
		
		for(int i=0;i<table.size();i++)
		{
			try 
			{
				String classname = table.get(Integer.toString(i+1)).toString();
				System.out.println("Class Name is "+classname);				
				String tempclassname = gid.getId(classname);			
				if(QueryMap.containsKey(tempclassname))
				{
					Class c =Class.forName(packagename+CapitalChar.makeFirstCharCapital(classname));
					query = (Queryinterface) c.newInstance();
					query.initPool();
					try 
					{
						query.setObject(result.get(table.get(Integer.toString(i+1)).toString().toLowerCase()).toString().toLowerCase());
						query.setQueryMap(QueryMap);
					} 
					catch (Exception e) 
					{
						try 
						{
							System.out.println((Vector<Object>)QueryMap.get(tempclassname));
							query.setViewObject((Vector<Object>)QueryMap.get(tempclassname));
						}
						catch (Exception e1) 
						{
							// TODO Auto-generated catch block
							e1.printStackTrace();
						}
					}
					query.settablename(tablename);
					tablename=query.gettablename();
					query.setbuffer(buffer);
					query.setQuerybuffer(Querybuffer);
					query.setKey(Key);
					Key = query.getkey();
					query.setValue(value);
					value = query.getvalue();
					query.setReportName(ReportName);
					query.settid(tid);
					query.setCount(Querycount);
					query.setMaxcount(Querycount);
				//	query.setMincount(minCount);
					//Querycount=query.getcount();
					QueryMap.put(tempclassname, query);
				}
			}
			catch (Exception e) 
			{
				e.printStackTrace();
			}
		}	
	}
	
	/**
	 * @return
	 * @uml.property  name="queryName"
	 */
	public String getQueryName()
	{
		return QueryMap.get("query").toString();
	}
	public void setQueryName()
	{
		
	}
	
	/**
	 * This method evaluate query and put result into buffer
	 * @uml.property  name="result"
	 */
	public void getResult()
	{		
		for(int i=0;i<table.size();i++)
		{
			try 
			{
				String classname = table.get(Integer.toString(i+1)).toString();
				System.out.println("Class Name is "+classname);
				classname = gid.getId(classname).toLowerCase();
				if(QueryMap.containsKey(classname))
				{	
					query = (Queryinterface) QueryMap.get(classname);
					query.initializeData();
					query.getResult();
					buffer = query.getbuffer();
					Querybuffer = query.getQuerybuffer();
					tid= query.gettid();
					Filename = query.getReportname();
				}
			}
			catch (Exception e) 
			{
				e.printStackTrace();
			}
		}
	}
	/**
	 * set buffer  
	 * @param buffer : String array 
	 */
	public void setbuffer(String[] buffer) 
	{
		this.buffer = buffer;
	}
	/**
 	 * this method convert string array into hashtable 
	 * @param line ; String array
	 * @return hashtable : Hashtable 
	 */
	
	public Hashtable<Object, Object> gethashtabelofResult(String line[])
	{
		Hashtable<Object, Object> result = new Hashtable<Object, Object>();
		for(int i=0;i<line.length;i++)
		{	
			String splitline[] = line[i].split("\t");
			String value = splitline[Column.pv_index-1];
			if(value.equals("0"))
				value = splitline[Column.vt_index-1];		
			result.put(gid.getItem(splitline[Column.pid_index-1]), value);			
		}
		result=ConvertToLower.convertHashKey(result);
		return result;
	}

	public void generateReport()
	{	
			try 
			{
				File file = new File(Filename);
				if(!file.exists())
					file.createNewFile();
				RandomAccessFile raf = new RandomAccessFile(file,"rws");
				for(int i=0;i<buffer.length;i++)
				{
					raf.writeBytes(buffer[i]+"\n");
				}
			}
			catch (FileNotFoundException e) 
			{
				e.printStackTrace();
			} 
			catch (Exception e) 
			{
				e.printStackTrace();
			}
		
	}
	/**
	 * retrun buffer 
	 * @return buffer: String array  
	 */
	public String[] getbuffer()
	{
		return buffer;
	}
	/**
	 * return tablename 
	 * @return tablename:String  
	 * 
	 * 	 */
	public String gettablename() 
	{
		return tablename;
	}
	/**
	 * settablename() method takes following parameters
	 * @param tablename : table name of query
	 * settablename method set tablename of Condition class
	*/
	public void settablename(String tablename) 
	{ 
		this.tablename = tablename;
	}
	
	public static void main(String[] args) 
	{
		Query query = new Query();
		query.initPool();//query.setObject("6271");
		//query.setObject("6280");
		//query.setObject("6296");  //systemgenerate report for transaction
		//query.setObject("6347");  //Retailer upper report Report
		//query.setObject("6396"); 	//middle td report
		query.setObject("7296");	//middlie full report
		//query.setObject("6435");	
		//query.setObject("6254");
		query.setValue("4");
		query.settypeofreport("Systemgenerate");
		query.initializeData();
		query.updateReport();
		String buffer[] =query.getbuffer();
		for(int i=0;i<buffer.length;i++)
		{
			System.out.println(buffer[i]);
		}
	}


	/**
	 * @return
	 * @uml.property  name="querybuffer"
	 */
	public String[] getQuerybuffer() 
	{
		return buffer;
	}
	/**
	 * set key
	 * @param key  :String
	 * @uml.property  name="key"
	 */
	public void setKey(String key) 
	{
		this.Key = "no$";
	}

	/**
	 * @param value
	 * @uml.property  name="value"
	 */
	public void setValue(String value) 
	{
		this.value = value;
	}
	/**
	 * return key   
	 * @return key:String 
	 */
	public String getkey() 
	{
		return Key;
	}

	public String getvalue() 
	{
		return value;
	}

	/**
	 * @param QueryName
	 * @uml.property  name="queryName"
	 */
	public void setQueryName(String QueryName) 
	{
		this.QueryName = QueryName;
	}


	public String getReportname() 
	{
		return Filename;
	}


	public void setReportname(String Filename) 
	{
		this.ReportName = Filename;
	}

	
	/**
	 * @return
	 * @uml.property  name="query"
	 */
	public Hashtable<Object, Object> getQueryMap() 
	{
		return QueryMap;
	}


	
	/**
	 * return tid which is present in report_master 
	 * @return tid
	 */
	public String gettid() 
	{
		return tid;
	}
	/**
	 * set tid  
	 * @param tid :String 
	*/
	public void settid(String tid) 
	{
		this.tid =tid;	
	}

	/**
	 * this method evalute query and put result into buffer    
	 */
	public void addReport() 
	{	
		for(int i=0;i<table.size();i++)
		{
			try 
			{
				String classname = table.get(Integer.toString(i+1)).toString();
				System.out.println("Class Name is "+classname);
				classname = gid.getId(classname).toLowerCase();
				if(QueryMap.containsKey(classname))
				{	
					query = (Queryinterface) QueryMap.get(classname);
					query.setbuffer(buffer);
					query.setQuerybuffer(Querybuffer);
					query.settablename(tablename);
					query.setReportmap(Reportmap);
					query.setConditionMap(ConditionMap);
					query.settypeofreport(typeofreport);
					query.setreporton(reporton);
					query.initializeData();		
					query.setValue(value);
					query.setQuery(Query);
					
					query.addReport();						
					
					buffer = query.getbuffer();
					Querybuffer = query.getQuerybuffer();		
					value = query.getvalue();
					tid= query.gettid();
					tablename = query.gettablename();
					Filename = query.getReportname();
					Query = query.getQuery();
				}
			}
			catch (Exception e) 
			{
				e.printStackTrace();
			}
		}
	}

	/**
	 * this method return buffer
	 * @return  buffer :String array
	 * @uml.property  name="buffer"
	 */
	public String[] getBuffer() 
	{
		return buffer;
	}


	/**
	 * @param process
	 * @uml.property  name="process"
	 */
	public void setProcess(String process)
	{
		this.process = process;
	}


	/**
	 * @return
	 * @uml.property  name="reportName"
	 */
	public String getReportName() 
	{
		return ReportName;
	}


	/**
	 * @param buffer
	 * @uml.property  name="buffer"
	 */
	public void setBuffer(String[] buffer) 
	{	
		this.buffer = buffer;
	}


	/**
	 * @param ReportName
	 * @uml.property  name="reportName"
	 */
	public void setReportName(String ReportName) 
	{
		this.ReportName = ReportName;	
	}
	
		
	public void queryProcess(){
		for(int i=0;i<table.size();i++)
		{
			try 
			{
				String classname = table.get(Integer.toString(i+1)).toString();
				System.out.println("Class Name is "+classname);
				classname = gid.getId(classname).toLowerCase();
				if(QueryMap.containsKey(classname))
				{	
					query = (Queryinterface) QueryMap.get(classname);
					
					query.setViewObject(queryVector);
					
					query.setbuffer(buffer);
					query.setQuerybuffer(Querybuffer);
					query.settablename(tablename);
					query.setReportmap(Reportmap);
					query.setConditionMap(ConditionMap);
					query.settypeofreport(typeofreport);
					query.setreporton(reporton);
					query.initializeData();		
					query.setValue(value);
					query.setQuery(Query);
					
					query.queryProcess();						
					
					buffer = query.getbuffer();
					Querybuffer = query.getQuerybuffer();		
					value = query.getvalue();
					tid= query.gettid();
					tablename = query.gettablename();
					Filename = query.getReportname();
					Query = query.getQuery();
				}
			}
			catch (Exception e) 
			{
				e.printStackTrace();
			}
		}
	}
	
	
	
	

	
	
	
	
	
	
	
	
	/**
	 * when process is mod then updateReport is call  
	 */
	public void updateReport()
	{	
		for(int i=0;i<table.size();i++)
		{
			try 
			{
				String classname = table.get(Integer.toString(i+1)).toString();
				System.out.println("Class Name is "+classname);
				classname = gid.getId(classname).toLowerCase();
				if(QueryMap.containsKey(classname))
				{	
					query = (Queryinterface) QueryMap.get(classname);
					query.setbuffer(buffer);
					query.setQuerybuffer(Querybuffer);
					query.settablename(tablename);
					query.setReportmap(Reportmap);
					query.setConditionMap(ConditionMap);
					query.settypeofreport(typeofreport);
					query.setreporton(reporton);
					query.initializeData();		
					query.setValue(value);
					query.setQuery(Query);
					
					query.updateReport();						
					
					buffer = query.getbuffer();
					Querybuffer = query.getQuerybuffer();		
					value = query.getvalue();
					tid= query.gettid();
					tablename = query.gettablename();
					Filename = query.getReportname();
					Query = query.getQuery();
				}
			}
			catch (Exception e) 
			{
				e.printStackTrace();
			}
		}
	} 


	/**
	 * @return
	 * @uml.property  name="key"
	 */
	public String getKey() 
	{
		return Key;
	}
	
	public String[] executeQuery(){return null;}
	

	public void settypeofreport(String typeofreport) 
	{
		this.typeofreport =typeofreport;
	}
	/**
	 * @param QueryMap
	 * @uml.property  name="query"
	 */
	public void setQueryMap(Hashtable<Object, Object> QueryMap) 
	{
		this.QueryMap.putAll(QueryMap);
	}
	/**
	 * @param ReportMap
	 * @uml.property  name="reportmap"
	 */
	public void setReportmap(Hashtable<Object, Object> ReportMap) 
	{
		this.Reportmap.putAll( ReportMap);
	}
	public void setreporton(String reporton) 
	{
		this.reporton = reporton; 
	}
	@SuppressWarnings("unchecked")
	public void setViewObject(String value, char ch) 
	{	
		Hashtable<Object,Object> ReportMap =new Hashtable<Object,Object>();
		try 
		{	
			ResultSet rs = DBManager.getSelect("SELECT * FROM command where msgtype='report_master' and process='view'  and message='query' order by order1");
			int indexofnextspchar=1;
			while(rs.next() && value.length()!=0)
			{
				String spchar =rs.getString("spchar"); 
				String Fieldname =rs.getString("fieldname");
				if(value.indexOf(spchar)!=-1)
				{
					indexofnextspchar = Index.indexOf(value, spchar, 1);
					if(indexofnextspchar==-1)
							indexofnextspchar = value.length();
					String newvalue="";
					if(!rs.isLast())
						 newvalue = value.substring(1, indexofnextspchar);
					else
						newvalue =value.substring(Fieldname.length()+1);
					String MasteridofField = gid.getId(Fieldname);
					if(!MasteridofField.equals("0"))
						Fieldname = MasteridofField;
					ReportMap.put(Fieldname, newvalue);
					value = value.substring(indexofnextspchar);
				}
				else
				{
					ReportMap.put(Fieldname, value);
					value ="";
				}
			}
			//if(table.isEmpty())
				//table.put(Key, value);
			//ReportMap.put(Key,table);
				
		} catch (Exception e) 
		{
			e.printStackTrace();
		}

		Set s1 = ReportMap.keySet();
		Iterator<Object> reportiterator= s1.iterator();
		Queryinterface query;
		String packagename ="query.query.";
		while(reportiterator.hasNext()) 
		{
			try
			{
				String Classname = reportiterator.next().toString();
				value = ReportMap.get(Classname).toString();
				Classname= gid.getItem(Classname);
				Class c =Class.forName(packagename+CapitalChar.makeFirstCharCapital(Classname));
				query = (Queryinterface) c.newInstance();
				query.initPool();
				ResultSet rs = DBManager.getSelect("SELECT * FROM command where msgtype='report_master' and message='"+Classname +"' and process='view' order by order1");
				ch='0';
				if(rs.next())
				{
					ch = rs.getString("spchar").toCharArray()[0];
				}	
				query.setViewObject(value.toString().replace("\"","").substring(Classname.length()+1),ch);
				//query.setQueryMap((Hashtable<Object, Object>)ReportMap.get(Classname));
				query.settablename("report_master");
				query.setbuffer(this.Querybuffer);
			   // query.initializeData();
				query.addReport();
				this.Querybuffer =query.getbuffer();			
				
			} 
			catch (ClassNotFoundException e) 
			{
				e.printStackTrace();
			} 
			catch (InstantiationException e)
			{
				e.printStackTrace();
			} 
			catch (Exception e) 
			{
				e.printStackTrace();
			}
		}
		    
	}
	public void setViewObject(Vector<Object> PropertyMap) 
	{	
		this.QueryMap.putAll((Map<? extends Object, ? extends Object>) PropertyMap.get(0));
		System.out.println(QueryMap);
		this.QueryMap = gid.ConvertKeytoMasterId(this.QueryMap);
	}
	
	/**
	 * @param Query
	 * @uml.property  name="query"
	 */
	public void setQuery(String Query)
	{
		this.Query = Query;
	}
	/**
	 * @return
	 * @uml.property  name="query"
	 */
	public String getQuery() 
	{
		return Query;
	}
	
	public int getcount() 
	{	
		return Querycount;
	}
	
	public void setCount(int count) 
	{
		this.Querycount=count+1;
	}
	@SuppressWarnings("static-access")
	public void setMaxcount(int count)
	{
		if(QueryMaxcount<Querycount)
			this.QueryMaxcount = Querycount;
	}
	public void buildQuery() 
	{
		for(int i=0;i<table.size();i++)
		{
			try 
			{
				String classname = table.get(Integer.toString(i+1)).toString();
				System.out.println("Class Name is "+classname);
				classname = gid.getId(classname).toLowerCase();
				if(QueryMap.containsKey(classname))
				{	
					query = (Queryinterface) QueryMap.get(classname);
					query.setQuerybuffer(Querybuffer);
					query.settablename(tablename);
					query.setReportmap(Reportmap);
					query.setConditionMap(ConditionMap);
					query.settypeofreport(typeofreport);
					query.setreporton(reporton);
					query.setbuffer(buffer);
					query.setQuerybuffer(Querybuffer);
					query.setValue(value);
					
					query.setQuery(Query);
					query.initializeData();		
					query.buildQuery();
					buffer =query.getbuffer();
					Querybuffer = query.getQuerybuffer();
					Query = query.getQuery();
					Querycount=query.getcount();				
					Querybuffer = query.getQuerybuffer();		
					value = query.getvalue();
					tid= query.gettid();
					tablename = query.gettablename();
					Filename = query.getReportname();
				}
			}
			catch (Exception e) 
			{
				e.printStackTrace();
			}
		}
	
	}
	/**
	 * @param QueryMap
	 * @uml.property  name="condition"
	 */
	public void setConditionMap(Vector<Object> QueryMap)
	{
		this.ConditionMap.addAll(QueryMap);
	}


	
	public void setMincount(int count) 
	{
		if(minCount<count)
			this.minCount = count;
	}
}
